package com.haixiaoke.saas.lock.service.impl;

import java.time.LocalDate;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.haixiaoke.saas.common.constant.DeviceLockConstants;
import com.haixiaoke.saas.common.constant.HttpStatus;
import com.haixiaoke.saas.common.core.domain.AjaxResult;
import com.haixiaoke.saas.common.core.page.TableDataInfo;
import com.haixiaoke.saas.common.utils.DateUtils;
import com.haixiaoke.saas.lock.domain.DeviceLock;
import com.haixiaoke.saas.lock.domain.LockFace;
import com.haixiaoke.saas.lock.domain.LockPwd;
import com.haixiaoke.saas.lock.mapper.DeviceLockMapper;
import com.haixiaoke.saas.lock.service.IDeviceLockService;
import com.haixiaoke.saas.lock.service.ILockFaceService;
import com.haixiaoke.saas.lock.service.ILockPwdService;
import com.haixiaoke.saas.user.domain.UserConsumer;
import com.haixiaoke.saas.user.service.IUserConsumerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 设备锁Service业务层处理
 *
 * @author panda
 * @date 2025-06-26
 */
@Service
public class DeviceLockServiceImpl implements IDeviceLockService {
    @Autowired
    private DeviceLockMapper deviceLockMapper;
    @Autowired
    private LockDevicesService lockDevicesService;
    @Autowired
    private ILockFaceService lockFaceService;
    @Autowired
    private ILockPwdService lockPwdService;
    @Autowired
    private IUserConsumerService userConsumerService;

    /**
     * 查询设备锁
     *
     * @param lockId 设备锁主键
     * @return 设备锁
     */
    @Override
    public DeviceLock selectDeviceLockByLockId(Long lockId) {
        return deviceLockMapper.selectDeviceLockByLockId(lockId);
    }

    /**
     * 获取锁型号列表
     */
    @Override
    public JSONObject modelList() {
        return lockDevicesService.modelList();
    }

    /**
     * 查询设备锁列表
     *
     * @param deviceLock 设备锁
     * @return 设备锁
     */
    @Override
    public List<DeviceLock> selectDeviceLockList(DeviceLock deviceLock) {
        return deviceLockMapper.selectDeviceLockList(deviceLock);
    }

    /**
     * 新增设备锁
     *
     * @param deviceLock 设备锁
     * @return 结果
     */
    @Override
    @Transactional
    public AjaxResult manageInsertDeviceLock(DeviceLock deviceLock) {
        if (StrUtil.isBlank(deviceLock.getLockMac()) || StrUtil.isBlank(deviceLock.getHouseId())) {
            return AjaxResult.error("设备数据异常");
        }
        List<Map<String, Object>> maps = deviceLockMapper.checkHouseIdAndMac(deviceLock);
        if (CollectionUtil.isNotEmpty(maps)) {
            for (Map<String, Object> map : maps) {
                if (Integer.parseInt(map.get("num").toString()) > 0) {
                    String type = map.get("type").toString();
                    switch (type) {
                        case "1":
                            return AjaxResult.error("该房间已被绑定,请重新选择房间");
                        case "2":
                            return AjaxResult.error("该锁已被绑定,请检查mac是否正确");
                    }
                }
            }
        }
        Date nowDate = DateUtils.getNowDate();
        deviceLock.setCreateTime(nowDate);
        //创建智能锁
        lockDevicesService.createSmartLock(deviceLock);
        int result = deviceLockMapper.insertDeviceLock(deviceLock);
        if (result > 0) {
            StringBuilder errMsg = new StringBuilder("授权失败的用户：");
            List<LockFace> lockFaceList = new ArrayList<>();
            LocalDate nowLocalDate = LocalDate.now();
            List<String> phoneList = deviceLock.getLockFaceList().stream().map(LockFace::getUserPhone).filter(StrUtil::isNotBlank).collect(Collectors.toList());
            Map<String, UserConsumer> userMap = null;
            if (!phoneList.isEmpty()) {
                List<UserConsumer> users = userConsumerService.selectUserByPhoneList(phoneList);
                if (CollectionUtil.isNotEmpty(users)) {
                    userMap = users.stream().collect(Collectors.toMap(UserConsumer::getUserPhone, x -> x));
                }
            }
            for (LockFace lockFace : deviceLock.getLockFaceList()) {
                try {
                    if (StrUtil.equals(DeviceLockConstants.AUTH_TIME_TYPE_LONG, lockFace.getAuthTimeType())) {
                        Date date = DateUtils.addYears(lockFace.getAuthStartTime(), 20);
                        lockFace.setAuthEndTime(date);
                    }
                    lockFace.setLockId(deviceLock.getLockId());
                    AjaxResult ajaxResult = lockFaceService.checkParam(lockFace);
                    if (ajaxResult != null) {
                        errMsg.append(lockFace.getUserName()).append("，");
                        continue;
                    }
                    LocalDate startTime = lockFace.getAuthStartTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                    if (nowLocalDate.isAfter(startTime)) {
                        errMsg.append(lockFace.getUserName()).append("，");
                        continue;
                    }
                    if (StrUtil.isNotBlank(lockFace.getUserPhone())) {
                        UserConsumer user = null;
                        if (userMap != null) {
                            user = userMap.get(lockFace.getUserPhone());
                        }
                        if (ObjectUtil.isEmpty(user)) {
                            user = new UserConsumer();
                            user.setUserPhone(lockFace.getUserPhone());
                            user.setNickName("未命名");
                            user.setUserName(lockFace.getUserName());
                            user.setCreateTime(nowDate);
                            userConsumerService.insertUserConsumer(user);
                        }
                        lockFace.setConUserId(user.getUserId());
                    }
                    String identification = lockDevicesService.getIdentification();
                    lockFace.setIdentification(identification);
                    lockFace.setCreateTime(nowDate);
                    lockFace.setCreateBy(deviceLock.getCreateBy());
                    if (StrUtil.isNotBlank(lockFace.getFaceImage())) {
                        lockDevicesService.createLockFace(lockFace.getFaceImage(), deviceLock.getLockMac(), identification, lockFace.getAuthStartTime(), lockFace.getAuthEndTime());
                    }
                    lockFaceList.add(lockFace);
                } catch (Exception e) {
                    errMsg.append(lockFace.getUserName()).append("，");
                }
            }

            if (!lockFaceList.isEmpty()) {
                lockFaceService.insertBatchLockFace(lockFaceList);
            }

            return StrUtil.equals(errMsg.toString(), "授权失败的用户：") ? AjaxResult.success() : AjaxResult.error(errMsg + "请重新授权");
        }
        return AjaxResult.success();
    }

    /**
     * 修改设备锁
     *
     * @param deviceLock 设备锁
     * @return 结果
     */
    @Override
    public int updateDeviceLock(DeviceLock deviceLock) {
        deviceLock.setUpdateTime(DateUtils.getNowDate());
        return deviceLockMapper.updateDeviceLock(deviceLock);
    }

    /**
     * 批量删除设备锁
     *
     * @param lockIds 需要删除的设备锁主键
     * @return 结果
     */
    @Override
    public int deleteDeviceLockByLockIds(Long[] lockIds) {
        return deviceLockMapper.deleteDeviceLockByLockIds(lockIds);
    }

    /**
     * 删除设备锁信息
     *
     * @param lockId 设备锁主键
     * @return 结果
     */
    @Override
    public AjaxResult deleteDeviceLockByLockId(Long lockId) {
        DeviceLock deviceLock = deviceLockMapper.selectDeviceLockByLockId(lockId);
        if (ObjectUtil.isEmpty(deviceLock)) {
            return AjaxResult.error("设备锁不存在");
        }
        lockDevicesService.removeLock(deviceLock.getLockMac());
        lockFaceService.deleteLockFaceByLockId(lockId);
        lockPwdService.deleteLockPwdByLockId(lockId);
        int result = deviceLockMapper.deleteDeviceLockByLockId(lockId);
        return result > 0 ? AjaxResult.success() : AjaxResult.error();
    }

    @Override
    public List<DeviceLock> flatSelectDeviceLockList(DeviceLock deviceLock) {
        return deviceLockMapper.flatSelectDeviceLockList(deviceLock);
    }

    @Override
    public TableDataInfo unlockingRecord(Long lockId, Date unlockTime, String userName, Integer unlockType, Integer pageNum, Integer pageSize) {
        TableDataInfo rspData = new TableDataInfo();
        rspData.setCode(HttpStatus.SUCCESS);
        rspData.setMsg("查询成功");
        rspData.setRows(null);
        rspData.setTotal(0);

        DeviceLock deviceLock = deviceLockMapper.selectDeviceLockByLockId(lockId);
        if (ObjectUtil.isEmpty(deviceLock)) {
            rspData.setMsg("设备锁不存在");
            return rspData;
        }

        StringBuilder params = new StringBuilder();
        params.append("?lockSn=").append(deviceLock.getLockMac());
        String stringTime = DateUtil.formatDate(deviceLock.getCreateTime());
        Date createTime = DateUtil.parse(stringTime, "yyyy-MM-dd");
        Date nowDate = DateUtils.getNowDate();
        if (ObjectUtil.isNotNull(unlockTime)) {
            if (DateUtil.compare(unlockTime, createTime) < 0) {
                unlockTime = createTime;
            }
            params.append("&params%5BbeginUnlockTime%5D=").append(DateUtil.format(unlockTime, "yyyy-MM-dd"));
            params.append("&params%5BendUnlockTime%5D=").append(DateUtil.format(nowDate, "yyyy-MM-dd"));
        } else {
            params.append("&params%5BbeginUnlockTime%5D=").append(DateUtil.format(createTime, "yyyy-MM-dd"));
            params.append("&params%5BendUnlockTime%5D=").append(DateUtil.format(nowDate, "yyyy-MM-dd"));
        }

        if (ObjectUtil.isNotNull(unlockType)) {
            params.append("&unlockType=").append(unlockType);
            if (DeviceLockConstants.LOCK_TYPE_FACE_OPEN.equals(unlockType)) {
                if (StrUtil.isNotEmpty(userName)) {
                    LockFace lockFace = lockFaceService.selectLockFaceByLockIdAndUserName(lockId, userName);
                    if (ObjectUtil.isEmpty(lockFace)) {
                        return rspData;
                    }
                    params.append("&identification=").append(lockFace.getIdentification());

                }
            }
        }

        if (ObjectUtil.isNotNull(pageNum) && ObjectUtil.isNotNull(pageSize)) {
            params.append("&pageNum=").append(pageNum);
            params.append("&pageSize=").append(pageSize);
        }

        JSONObject jsonObject = lockDevicesService.unlockingRecord(params.toString());

        JSONArray jsonArray = jsonObject.getJSONArray("rows");
        List<Map> maps = JSONArray.parseArray(jsonArray.toJSONString(), Map.class);

        if (maps.size() > 0) {
            List<String> identifications = maps.stream().map(x -> x.get("identification").toString()).distinct().collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(identifications)) {
                List<LockPwd> pwdList = lockPwdService.selectLockListByIdentifications(identifications);
                List<LockFace> faceList = lockFaceService.selectLockListByIdentifications(identifications);
                Map<String, String> pwds = pwdList.stream().collect(Collectors.toMap(LockPwd::getIdentification, LockPwd::getUserName));
                Map<String, String> faces = faceList.stream().collect(Collectors.toMap(LockFace::getIdentification, LockFace::getUserName));
                maps.forEach(x -> {
                    String face = faces.get(x.get("identification").toString());
                    String pwd = pwds.get(x.get("identification").toString());
                    x.put("name", StrUtil.isBlank(face) ? pwd : face);
                });
            }
        }
        rspData.setRows(maps);
        rspData.setTotal((Integer) jsonObject.get("total"));
        return rspData;
    }

    @Override
    public List<String> selectDeviceLockMacList() {
        return deviceLockMapper.selectDeviceLockMacList();
    }
}
